(require <console.scm.manager>)

(define-constant console-window-title "Console")
(define (exit) 
  (java.lang.System:exit 0))
(define-constant frame :: javax.swing.JFrame (javax.swing.JFrame console-window-title))
(define-constant in_r :: gnu.text.QueueReader (gnu.text.QueueReader))
(define-constant console :: console.window.SwingMessageArea (console.window.SwingMessageArea #f in_r))
(define-constant top-panel :: javax.swing.JPanel (javax.swing.JPanel))
(define (make-console-window frame :: javax.swing.JFrame )
      ;(frame:setIconImage ((console.Utilities:loadIcon "app.ico"):getImage))
      (console:setFont (java.awt.Font "Courier" (<java.awt.Font>:.PLAIN) ((console:getFont):getSize)))
      (let* ((out-p (gnu.mapping.OutPort (console:getStdout) #t "<msg_stdout>"))
             (err-p (gnu.mapping.OutPort (console:getStderr) #t "<msg_stderr>"))
             (in-p (console.window.SwingInPort in_r (gnu.text.Path  "<msg_stdin>") out-p console))
             (scheme (kawa.standard.Scheme))
             (repl (kawa.repl scheme))
             (thread (gnu.mapping.Future:make repl (interaction-environment) in-p out-p err-p)))
         (thread:start))
      (let* ((console-scroll (javax.swing.JScrollPane console))
             (split-pane (javax.swing.JSplitPane (javax.swing.JSplitPane:.VERTICAL_SPLIT) #f top-panel console-scroll)))
         ;(split-pane:setDividerLocation 300)
         ((frame:getContentPane):add split-pane)
         (console-scroll:setPreferredSize (java.awt.Dimension 640 200))
         (console:setBackground ((console:getBackground):darker))
         (console-scroll:setVerticalScrollBarPolicy (<javax.swing.ScrollPaneConstants>:.VERTICAL_SCROLLBAR_ALWAYS))))
(define (unix-system?) (string=? (<java.lang.System>:getProperty "path.separator") ":"))
(define (console-prompter port)
	(let ((state (input-port-read-state port)))
		(if (char=? state #\Newline)
			""
			(string-append
				(if (char=? state #\Space)
					"#|Sim:"
					(string-append "#|" (make-string 1 state) "---:"))
				(number->string (input-port-line-number port))
				"|# "))))

(define (add-sub-menu menu-bar :: javax.swing.JMenu m)
  (if (list? m)
    (letrec ((menu :: javax.swing.JMenu (javax.swing.JMenu (as <java.lang.String> (car m))))
             (next (lambda (l)
                     (if (> (length l) 0)
                       (begin
                         (if (instance? (car l) <javax.swing.AbstractAction>)
                           (menu:add (car l))
                           (if (list? (car l))
                             (add-sub-menu menu (car l))
                             (menu:setMnemonic (car l))))
                         (next (cdr l)))))))
      (next (cdr m))
      (menu-bar:add menu))
    (menu-bar:add (<javax.swing.Box>:createHorizontalGlue))))


(define (add-to-menu-bar menu-bar :: javax.swing.JMenuBar m)
  (if (list? m)
    (letrec ((menu :: javax.swing.JMenu (javax.swing.JMenu (as <java.lang.String> (car m))))
             (next (lambda (l)
                     (if (> (length l) 0)
                       (begin
                         (if (instance? (car l) <javax.swing.AbstractAction>)
                           (menu:add (car l))
                           (if (list? (car l))
                             (add-sub-menu menu (car l))
                             (menu:setMnemonic (car l))))
                         (next (cdr l)))))))
      (next (cdr m))
      (menu-bar:add menu))
    (menu-bar:add (<javax.swing.Box>:createHorizontalGlue))))

(define (make-menu m)
  (letrec ((menu-bar (javax.swing.JMenuBar))
           (next (lambda (l)
                   (if (> (length l) 0)
                     (begin
                       (add-to-menu-bar menu-bar (car l))
                       (next (cdr l)))))))
    (next m)
    (frame:setJMenuBar menu-bar)
    (frame:pack)))
(define (add-to-menu m)
  (letrec ((menu-bar (frame:getJMenuBar))
           (next (lambda (l)
                   (if (> (length l) 0)
                     (begin
                       (add-to-menu-bar menu-bar (car l))
                       (next (cdr l)))))))
    (next m)
    (frame:setJMenuBar menu-bar)
    (frame:pack)))

(define (make-frame . args)
  (begin
  	(frame:setDefaultCloseOperation (javax.swing.JFrame:.EXIT_ON_CLOSE))
	  (make-console-window frame)
 		(frame:pack)
      (if (> (length args) 0)
        (frame:setIconImage (car args)))
 	  (frame:setVisible #t)))
(define (send-command thunk action . args)
  (let ((caption (if (= (length args) 1) (car args) "")))
    (in_r:append (string-append "(display \"==command invoked== " caption "\")"))
    (in_r:append "\n")
    (task-exe caption thunk action 0)))

(define (select-script-file)
  (let ((dialog (<javax.swing.JFileChooser>)))
    (dialog:setCurrentDirectory (<java.io.File> "."))
    (dialog:setDialogTitle "Select Scheme Script File To Be Executed")
    (dialog:setApproveButtonText "Run")
    (begin
    	(define-simple-class <scm-filter> (<javax.swing.filechooser.FileFilter>)
				((accept pathname :: <java.io.File>) :: <boolean> (or (pathname:isDirectory) ((pathname:getName):endsWith ".scm")))
				((getDescription) :: <String> "Scheme Script (*.scm)"))
			(dialog:setFileFilter (<scm-filter>)))
    (let ((result (dialog:showOpenDialog frame)))
      (if (= result 0)
        (dialog:getSelectedFile)
        ""))))
;(define (show-about task-id action)
;  (<javax.swing.JOptionPane>:showMessageDialog #!null (string-append "jiffy task id:" (number->string task-id)) "jiffy" 0))
(define (load-script-file task-id action)
  (in_r:append "(let ((f ((select-script-file):toString))) (if ((<java.io.File> (as <java.lang.String> f)):exists) (load f)) (newline))\n"))
(define (add-to-history str)
  (console:_updateHistory str))

(define-simple-class integerupdater (java.beans.PropertyChangeListener)
       (action :: console.ConsoleAction)
       (id-name :: <string>)
       ((*init* (i-action :: console.ConsoleAction) (i-id-name :: <string>))
        (set! action i-action)
        (set! id-name i-id-name))
       ((propertyChange evt :: java.beans.PropertyChangeEvent) :: <void> 
        (action:putValue (javax.swing.AbstractAction:.NAME) ((string-append id-name " [" (if (number? (action:getValue id-name)) (number->string (action:getValue id-name)) (action:getValue id-name)) "]"):toString))))


